<template>
  <div class="expose-child">
    <h4 class="font-medium text-gray-800 mb-3">Expose 子组件方法和数据：</h4>

    <div class="space-y-4">
      <!-- 子组件内部状态 -->
      <div class="internal-state">
        <h5 class="text-sm font-semibold text-gray-700 mb-2">子组件内部状态</h5>
        <div class="space-y-2">
          <div class="state-item">
            <span class="state-label">内部计数器:</span>
            <span class="state-value">{{ internalCount }}</span>
          </div>
          <div class="state-item">
            <span class="state-label">状态信息:</span>
            <span class="state-value">{{ statusMessage }}</span>
          </div>
          <div class="state-item">
            <span class="state-label">最后操作:</span>
            <span class="state-value">{{ lastAction }}</span>
          </div>
        </div>
      </div>

      <!-- 子组件内部操作按钮 -->
      <div class="internal-actions">
        <h5 class="text-sm font-semibold text-gray-700 mb-2">子组件内部操作</h5>
        <div class="grid grid-cols-2 gap-2">
          <button
            @click="incrementInternal"
            class="px-3 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 text-sm"
          >
            内部 +1
          </button>
          <button
            @click="decrementInternal"
            class="px-3 py-2 bg-red-500 text-white rounded hover:bg-red-600 text-sm"
          >
            内部 -1
          </button>
          <button
            @click="resetInternal"
            class="px-3 py-2 bg-gray-500 text-white rounded hover:bg-gray-600 text-sm"
          >
            重置计数
          </button>
          <button
            @click="randomizeInternal"
            class="px-3 py-2 bg-purple-500 text-white rounded hover:bg-purple-600 text-sm"
          >
            随机数值
          </button>
        </div>
      </div>

      <!-- 消息日志 -->
      <div class="message-log">
        <h5 class="text-sm font-semibold text-gray-700 mb-2">操作日志</h5>
        <div class="bg-gray-100 p-3 rounded max-h-32 overflow-y-auto">
          <div v-for="(log, index) in operationLogs" :key="index" class="text-xs mb-1">
            <span class="text-gray-500">{{ log.time }}</span>
            <span
              class="ml-2"
              :class="log.type === 'external' ? 'text-blue-600' : 'text-green-600'"
            >
              {{ log.message }}
            </span>
          </div>
          <div v-if="operationLogs.length === 0" class="text-xs text-gray-500">暂无操作记录</div>
        </div>
      </div>
    </div>

    <!-- Expose 说明 -->
    <div class="mt-4 p-3 bg-orange-50 border border-orange-200 rounded">
      <h5 class="text-sm font-medium text-orange-800 mb-2">🔓 Expose 说明</h5>
      <ul class="text-xs text-orange-700 space-y-1">
        <li>• defineExpose() 暴露子组件的方法和数据</li>
        <li>• 父组件通过 ref 获取子组件实例</li>
        <li>• 可以直接调用子组件的方法</li>
        <li>• 可以访问子组件暴露的数据</li>
        <li>• 打破了组件封装，谨慎使用</li>
      </ul>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue'

// 子组件内部状态
const internalCount = ref(0)
const statusMessage = ref('准备就绪')
const lastAction = ref('无')

// 操作日志
interface OperationLog {
  time: string
  message: string
  type: 'internal' | 'external'
}

const operationLogs = ref<OperationLog[]>([])

// 添加日志
const addLog = (message: string, type: 'internal' | 'external' = 'internal') => {
  operationLogs.value.push({
    time: new Date().toLocaleTimeString(),
    message,
    type,
  })

  // 限制日志数量
  if (operationLogs.value.length > 10) {
    operationLogs.value.shift()
  }
}

// 子组件内部方法
const incrementInternal = () => {
  internalCount.value++
  lastAction.value = '内部递增'
  addLog(`内部计数器递增: ${internalCount.value}`)
}

const decrementInternal = () => {
  internalCount.value--
  lastAction.value = '内部递减'
  addLog(`内部计数器递减: ${internalCount.value}`)
}

const resetInternal = () => {
  internalCount.value = 0
  lastAction.value = '内部重置'
  statusMessage.value = '已重置'
  addLog('内部计数器已重置')
}

const randomizeInternal = () => {
  const randomValue = Math.floor(Math.random() * 100)
  internalCount.value = randomValue
  lastAction.value = '内部随机化'
  statusMessage.value = `随机值: ${randomValue}`
  addLog(`内部计数器随机化: ${randomValue}`)
}

// 暴露给父组件的方法和数据
const childMethod = (message: string) => {
  statusMessage.value = `外部调用: ${message}`
  lastAction.value = '外部方法调用'
  addLog(`收到外部调用: ${message}`, 'external')

  // 模拟一些处理
  setTimeout(() => {
    statusMessage.value = '外部调用处理完成'
  }, 1000)
}

const getChildData = () => {
  const data = {
    internalCount: internalCount.value,
    statusMessage: statusMessage.value,
    lastAction: lastAction.value,
    logCount: operationLogs.value.length,
    timestamp: new Date().toISOString(),
  }

  addLog('数据被外部访问', 'external')
  return data
}

const setChildCount = (count: number) => {
  internalCount.value = count
  lastAction.value = '外部设置计数'
  statusMessage.value = `外部设置计数为: ${count}`
  addLog(`计数被外部设置为: ${count}`, 'external')
}

const clearLogs = () => {
  operationLogs.value = []
  lastAction.value = '清空日志'
  addLog('日志已清空', 'external')
}

// 使用 defineExpose 暴露方法和数据
defineExpose({
  // 暴露方法
  childMethod,
  getChildData,
  setChildCount,
  clearLogs,

  // 暴露只读数据
  get count() {
    return internalCount.value
  },
  get status() {
    return statusMessage.value
  },
})
</script>

<style scoped lang="scss">
.expose-child {
  @apply border border-gray-200 rounded-lg p-4 bg-gray-50;
}

.internal-state,
.internal-actions,
.message-log {
  @apply p-3 bg-white rounded border border-gray-100;
}

.state-item {
  @apply flex justify-between items-center;
}

.state-label {
  @apply text-sm font-medium text-gray-600;
}

.state-value {
  @apply text-sm font-semibold text-gray-800 bg-gray-100 px-2 py-1 rounded;
}
</style>
